#include <Arduino.h>
#include "LEDMatrixDisplay.h"
#include "WiFiManager.h"
#include "TimeService.h"
#include "ButtonHandler.h"
#include "AmbientEffects.h"
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>

#define LED_PIN 8
#define LED_WIDTH 32
#define LED_HEIGHT 8
#define BTN_MODE_PIN  13

LEDMatrixDisplay<LED_PIN> ledMatrix(LED_WIDTH, LED_HEIGHT);
WiFiManager wifiManager("xiaomiWIFI", "hhz18394866900");
TimeService timeService;
ButtonHandler modeButton(BTN_MODE_PIN, true);

DeviceConfig currentConfig;

enum DisplayMode { TIME, DATE, AMBIENT_RAINBOW, AMBIENT_PURPLE };
DisplayMode currentMode = TIME;

uint8_t ambientHue = 0;
float purpleProgress = 0.0;
unsigned long lastPurpleUpdate = 0;
bool wifiConnected = false;
unsigned long lastWifiCheck = 0;
const unsigned long wifiCheckInterval = 5000;

// BLE服务
#define SERVICE_UUID        "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"

BLEServer *pServer;
BLEService *pService;
BLECharacteristic *pCharacteristic;

bool deviceConnected = false;
bool oldDeviceConnected = false;

class MyServerCallbacks: public BLEServerCallbacks {
    void onConnect(BLEServer* pServer) {
        deviceConnected = true;
        Serial.println("设备已连接");
    };

    void onDisconnect(BLEServer* pServer) {
        deviceConnected = false;
        Serial.println("设备已断开");
    }
};

class MyCallbacks: public BLECharacteristicCallbacks {
    void onWrite(BLECharacteristic *pCharacteristic) {
        std::string value = pCharacteristic->getValue();
        if (value.length() > 0) {
            Serial.print("收到蓝牙命令: ");
            for (int i = 0; i < value.length(); i++) {
                Serial.print(value[i]);
            }
            Serial.println();
            
            processBluetoothCommand(String(value.c_str()));
        }
    }
};

void processBluetoothCommand(String command) {
    int colonIndex = command.indexOf(':');
    if (colonIndex == -1) return;

    String cmdType = command.substring(0, colonIndex);
    String valueStr = command.substring(colonIndex+1);

    if (cmdType.equalsIgnoreCase("brightness")) {
        uint8_t brightness = valueStr.toInt();
        if (brightness >= 10 && brightness <= 255) {
            ledMatrix.setBrightness(brightness);
            currentConfig.brightness = brightness;
            wifiManager.saveConfig(currentConfig);
            Serial.print("设置亮度: ");
            Serial.println(brightness);
        }
    } else if (cmdType.equalsIgnoreCase("hourColor")) {
        CRGB color = parseColor(valueStr);
        ledMatrix.setTimeColor(color, currentConfig.minColor, currentConfig.secColor);
        currentConfig.hourColor = color;
        wifiManager.saveConfig(currentConfig);
        Serial.println("设置小时颜色");
    } else if (cmdType.equalsIgnoreCase("minColor")) {
        CRGB color = parseColor(valueStr);
        ledMatrix.setTimeColor(currentConfig.hourColor, color, currentConfig.secColor);
        currentConfig.minColor = color;
        wifiManager.saveConfig(currentConfig);
        Serial.println("设置分钟颜色");
    } else if (cmdType.equalsIgnoreCase("secColor")) {
        CRGB color = parseColor(valueStr);
        ledMatrix.setTimeColor(currentConfig.hourColor, currentConfig.minColor, color);
        currentConfig.secColor = color;
        wifiManager.saveConfig(currentConfig);
        Serial.println("设置秒钟颜色");
    } else if (cmdType.equalsIgnoreCase("colonColor")) {
        CRGB color = parseColor(valueStr);
        ledMatrix.setColonColor(color);
        currentConfig.colonColor = color;
        wifiManager.saveConfig(currentConfig);
        Serial.println("设置冒号颜色");
    } else if (cmdType.equalsIgnoreCase("dateColor")) {
        CRGB color = parseColor(valueStr);
        ledMatrix.setDateColor(color);
        currentConfig.dateColor = color;
        wifiManager.saveConfig(currentConfig);
        Serial.println("设置日期颜色");
    } else if (cmdType.equalsIgnoreCase("weekActive")) {
        CRGB color = parseColor(valueStr);
        ledMatrix.setWeekColors(color, currentConfig.weekInactiveColor);
        currentConfig.weekActiveColor = color;
        wifiManager.saveConfig(currentConfig);
        Serial.println("设置当前星期颜色");
    } else if (cmdType.equalsIgnoreCase("weekInactive")) {
        CRGB color = parseColor(valueStr);
        ledMatrix.setWeekColors(currentConfig.weekActiveColor, color);
        currentConfig.weekInactiveColor = color;
        wifiManager.saveConfig(currentConfig);
        Serial.println("设置其他星期颜色");
    }
}

CRGB parseColor(String str) {
    int commaIndex1 = str.indexOf(',');
    int commaIndex2 = str.indexOf(',', commaIndex1+1);
    if (commaIndex1 == -1 || commaIndex2 == -1) return CRGB::Black;

    uint8_t r = str.substring(0, commaIndex1).toInt();
    uint8_t g = str.substring(commaIndex1+1, commaIndex2).toInt();
    uint8_t b = str.substring(commaIndex2+1).toInt();

    return CRGB(r, g, b);
}

void setup() {
    Serial.begin(115200);
    Serial.println("设备启动中...");
    
    pinMode(BTN_MODE_PIN, INPUT_PULLUP);
    ledMatrix.begin();
    
    // 加载配置
    wifiManager.loadConfig(currentConfig);
    
    // 应用配置
    ledMatrix.setBrightness(currentConfig.brightness);
    ledMatrix.setTimeColor(
        currentConfig.hourColor,
        currentConfig.minColor,
        currentConfig.secColor
    );
    ledMatrix.setColonColor(currentConfig.colonColor);
    ledMatrix.setDateColor(currentConfig.dateColor);
    ledMatrix.setWeekColors(
        currentConfig.weekActiveColor,
        currentConfig.weekInactiveColor
    );
    
    DisplayLayout& layout = ledMatrix.getLayout();
    layout.setTimePosition(2, 0);
    layout.setDatePosition(5, 1);
    
    // 显示连接状态
    ledMatrix.fillScreen(CRGB::Blue);
    delay(300);
    
    wifiManager.begin();
    
    // 连接状态动画
    for(int i = 0; i < 3; i++) {
        ledMatrix.fillScreen(CRGB::Blue);
        delay(200);
        ledMatrix.fillScreen(CRGB::Black);
        delay(200);
    }
    
    if(wifiManager.isConnected()) {
        timeService.begin();
        wifiConnected = true;
        
        IPAddress ip = WiFi.localIP();
        Serial.print("WiFi连接成功! IP地址: ");
        Serial.println(ip);
        
        // 显示IP最后两段
        ledMatrix.clear();
        uint8_t thirdOctet = ip[2];
        uint8_t fourthOctet = ip[3];
        
        // 计算起始位置（居中）
        uint8_t startX = (LED_WIDTH - 24) / 2; // 总宽度约18像素
        
        // 绘制第三段数字
        ledMatrix.getLayout().drawSmallDigit(ledMatrix.getLeds(), startX, 2, thirdOctet / 100, CRGB::Green);
        ledMatrix.getLayout().drawSmallDigit(ledMatrix.getLeds(), startX + 4, 2, (thirdOctet % 100) / 10, CRGB::Green);
        ledMatrix.getLayout().drawSmallDigit(ledMatrix.getLeds(), startX + 8, 2, thirdOctet % 10, CRGB::Green);
        
        // 绘制点
        ledMatrix.getLayout().drawColon(ledMatrix.getLeds(), startX + 12, 2, CRGB::Green);
        
        // 绘制第四段数字
        ledMatrix.getLayout().drawSmallDigit(ledMatrix.getLeds(), startX + 14, 2, fourthOctet / 100, CRGB::Green);
        ledMatrix.getLayout().drawSmallDigit(ledMatrix.getLeds(), startX + 18, 2, (fourthOctet % 100) / 10, CRGB::Green);
        ledMatrix.getLayout().drawSmallDigit(ledMatrix.getLeds(), startX + 22, 2, fourthOctet % 10, CRGB::Green);
        
        FastLED.show();
        
        Serial.print("显示IP最后两段: ");
        Serial.print(thirdOctet);
        Serial.print(".");
        Serial.println(fourthOctet);
        
        delay(5000);
    } else if (wifiManager.isAPMode()) {
        Serial.println("进入AP模式");
        
        IPAddress apIP = WiFi.softAPIP();
        Serial.print("AP模式IP: ");
        Serial.println(apIP);
        
        ledMatrix.clear();
        uint8_t thirdOctet = apIP[2];
        uint8_t fourthOctet = apIP[3];
        
        // 计算起始位置（居中）
        uint8_t startX = (LED_WIDTH - 24) / 2; // 总宽度约18像素
        
        // 绘制第三段数字
        ledMatrix.getLayout().drawSmallDigit(ledMatrix.getLeds(), startX, 2, thirdOctet / 100, CRGB::Yellow);
        ledMatrix.getLayout().drawSmallDigit(ledMatrix.getLeds(), startX + 4, 2, (thirdOctet % 100) / 10, CRGB::Yellow);
        ledMatrix.getLayout().drawSmallDigit(ledMatrix.getLeds(), startX + 8, 2, thirdOctet % 10, CRGB::Yellow);
        
        // 绘制点
        ledMatrix.getLayout().drawColon(ledMatrix.getLeds(), startX + 12, 2, CRGB::Yellow);
        
        // 绘制第四段数字
        ledMatrix.getLayout().drawSmallDigit(ledMatrix.getLeds(), startX + 14, 2, fourthOctet / 100, CRGB::Yellow);
        ledMatrix.getLayout().drawSmallDigit(ledMatrix.getLeds(), startX + 18, 2, (fourthOctet % 100) / 10, CRGB::Yellow);
        ledMatrix.getLayout().drawSmallDigit(ledMatrix.getLeds(), startX + 22, 2, fourthOctet % 10, CRGB::Yellow);
        
        // 显示AP标识
        ledMatrix.getLayout().drawDigit(ledMatrix.getLeds(), 0, 2, 10, CRGB::Red); // A
        ledMatrix.getLayout().drawDigit(ledMatrix.getLeds(), 4, 2, 11, CRGB::Red); // P
        FastLED.show();
        
        Serial.print("显示AP IP最后两段: ");
        Serial.print(thirdOctet);
        Serial.print(".");
        Serial.println(fourthOctet);
        
        delay(5000);
    }
    
    // 初始化BLE
    BLEDevice::init("ESP32_Clock");
    pServer = BLEDevice::createServer();
    pServer->setCallbacks(new MyServerCallbacks());
    pService = pServer->createService(SERVICE_UUID);
    pCharacteristic = pService->createCharacteristic(
        CHARACTERISTIC_UUID,
        BLECharacteristic::PROPERTY_READ |
        BLECharacteristic::PROPERTY_WRITE
    );

    pCharacteristic->setCallbacks(new MyCallbacks());
    pService->start();
    BLEAdvertising *pAdvertising = pServer->getAdvertising();
    pAdvertising->start();
    Serial.println("等待蓝牙客户端连接...");
}

void loop() {
    static unsigned long lastUpdate = 0;
    static unsigned long lastConfigCheck = 0;
    
    if(millis() - lastWifiCheck > wifiCheckInterval) {
        lastWifiCheck = millis();
        bool currentWifiStatus = wifiManager.isConnected();
        
        if(currentWifiStatus && !wifiConnected) {
            timeService.begin();
            wifiConnected = true;
        } 
        else if (!currentWifiStatus) {
            wifiConnected = false;
            wifiManager.attemptReconnect();
        }
    }
    
    if (millis() - lastConfigCheck > 30000) {
        lastConfigCheck = millis();
        
        DeviceConfig newConfig;
        wifiManager.loadConfig(newConfig);
        
        if (memcmp(&newConfig, &currentConfig, sizeof(DeviceConfig)) != 0) {
            currentConfig = newConfig;
            
            ledMatrix.setBrightness(currentConfig.brightness);
            ledMatrix.setTimeColor(
                currentConfig.hourColor,
                currentConfig.minColor,
                currentConfig.secColor
            );
            ledMatrix.setColonColor(currentConfig.colonColor);
            ledMatrix.setDateColor(currentConfig.dateColor);
            ledMatrix.setWeekColors(
                currentConfig.weekActiveColor,
                currentConfig.weekInactiveColor
            );
        }
    }
    
    if (modeButton.wasReleased()) {
        switch(currentMode) {
            case TIME: currentMode = DATE; break;
            case DATE: currentMode = AMBIENT_RAINBOW; break;
            case AMBIENT_RAINBOW: currentMode = AMBIENT_PURPLE; break;
            case AMBIENT_PURPLE: currentMode = TIME; break;
        }
        ledMatrix.clear();
        ledMatrix.show();
    }
    
    if (millis() - lastUpdate < 50) {
        delay(1);
        return;
    }
    lastUpdate = millis();
    
    // 处理蓝牙连接状态
    if (!deviceConnected && oldDeviceConnected) {
        delay(500); // 给蓝牙一点时间
        pServer->startAdvertising(); // 重新开始广播
        Serial.println("开始广播");
        oldDeviceConnected = deviceConnected;
    }
    if (deviceConnected && !oldDeviceConnected) {
        oldDeviceConnected = deviceConnected;
    }
    
    if (wifiConnected) {
        timeService.update();
        uint8_t dayOfWeek = timeService.getDayOfWeek();
        if (dayOfWeek > 6) dayOfWeek = 0;

        switch (currentMode) {
            case TIME:
                ledMatrix.displayTime(
                    timeService.getHours(),
                    timeService.getMinutes(),
                    timeService.getSeconds(),
                    dayOfWeek
                );
                break;
                
            case DATE: {
                TimeService::Date date = timeService.getDate();
                ledMatrix.drawDate(date.month, date.day, dayOfWeek, currentConfig.dateColor);
                break;
            }
                
            case AMBIENT_RAINBOW:
                AmbientEffects::rainbow(ledMatrix.getLeds(), LED_WIDTH, LED_HEIGHT, ambientHue);
                FastLED.show();
                break;
                
            case AMBIENT_PURPLE:
                AmbientEffects::purple(ledMatrix.getLeds(), LED_WIDTH * LED_HEIGHT, purpleProgress, lastPurpleUpdate);
                break;
        }
    } else {
        uint8_t errorHue = 0;
        errorHue += 2;
        
        for (uint8_t x = 0; x < LED_WIDTH; x++) {
            for (uint8_t y = 0; y < LED_HEIGHT; y++) {
                uint8_t pixelHue = errorHue + (x * 5) + (y * 3);
                int index = ledMatrix.getLayout().getLedIndex(x, y);
                if (index >= 0 && index < LED_WIDTH * LED_HEIGHT) {
                    ledMatrix.getLeds()[index] = CHSV(pixelHue, 255, 150);
                }
            }
        }
        
        uint8_t centerX = LED_WIDTH / 2;
        uint8_t centerY = LED_HEIGHT / 2;
        
        for (int i = -2; i <= 2; i++) {
            int index1 = ledMatrix.getLayout().getLedIndex(centerX + i, centerY + i);
            int index2 = ledMatrix.getLayout().getLedIndex(centerX + i, centerY - i);
            
            if (index1 >= 0) ledMatrix.getLeds()[index1] = CRGB::Red;
            if (index2 >= 0) ledMatrix.getLeds()[index2] = CRGB::Red;
        }
        
        FastLED.show();
    }
}